Remember?
Register
Back

Templating

By Monkeymatt last edited on Saturday, May 20, 2006 at 1:11:02 pm by Monkeymatt. Page 8.

<< Prev123456789Next >>

Complete code:

PHP Code

<?php
class Template{
    
// Define global variables
    
private $code=array(); // This will hold all of the code we get and all of the sections in a multidimensional array
    
private $file_root// Holds the main directory where the template files are stored, defined in constructor
    
private $current_level=0// Holds the current level in the level tracker (0 is the file, 1 and up are sections)
    
private $level_tracker=array(); // Holds a reference to the places in the main code array where we went through to get to where we are
    
private $current_item// Holds a reference to the current place in the $code array
    
private $printed=false// Whether we have given the output or not
    
    // Generic error function to help make error reporting easier
    
protected function error($function$message) {
        die(
"<b>Error</b><br />Function: $function<br />Message:$message");
    }
    
    
// Constructor, takes in file root and sets it in the global variable
    
public function __construct($file_root="./") {
        if (
$file_root == "") {
            
$file_root="./";
        } else if (!
is_dir($file_root)) {
            
$this->error("Constructor""$file_root is not a directory"); // Throw an error if the directory does not exist
        
}
        
// Now there are no errors
        
$this->file_root=$file_root// Set global variable
        
$this->code['base']['****code****']=''// For later
    
}
    
    
// Adds files 
    
public function add_file($file) {
        if (!
is_file($this->file_root.$file)) {
            
$this->error("add_file()""File '$file' does not exist.");
        }
        
$contents=file_get_contents($this->file_root.$file);
        if (empty(
$contents)) {
            
$this->error("add_file()""File '$file' is empty.");
        } else {
            
$this->code['base']['****code****'].=$contents// add $contents to the variable we initiated in the constructor
        
}
        
$this->level_tracker=array(); // clear of all other references because we started at the beginning again
        
$this->level_tracker[0]=&$this->code['base']; // Set bottom of level_tracker to be a reference to the base of the code array
        
$this->current_level=0;
        
$this->current_item=&$this->code['base']; // Current item is now the base of the code array, this variable can be used exactly the same as $level_tracker[0] right now
    
}
    
    
// Replaces references using __set special method (setting a variable calls this if the variable is not accessible to them)
    // e.x. $template->java="fun"; -- $name=java, $value=fun
    
public function __set($name$value) {
        if (
strpos($name"base_") === 0) { // starts with 'base_', do whole section
            
$name=substr($name5); // remove 'base_' from the beginning
            
$this->level_tracker[0]['****code****']=str_replace("{".$name."}"$value$this->level_tracker[0]['****code****']);
        } else {
            if (
$this->current_level 1) {
                
$this->error("value set""No Section Set (Use 'base_' before the term to do it in the whole of the file)");
            }
            
$num=$this->current_item['****current_iteration****']; // for below
            
if (empty($this->current_item[$num]['****code****'])) { // no code for current_item, so set it
                
$this->current_item[$num]['****code****']=$this->current_item['****code****'];
            }
            
$this->current_item[$num]['****code****']=str_replace("{".$name."}"$value$this->current_item[$num]['****code****']);
        }
    }
    
    
// Function to set section and extract code data from current item
    
public function set_section($section) {
        if (empty(
$this->current_item)) {
            
$this->error("set_section()""No handle set");
        }
        if (empty(
$section)) {
            
$this->error("set_section()""No section given");
        }
        
$found=false;
        
// Search down the level_tracker array until we find the requested section
        
for ($i=$this->current_level;$i>=0;$i--) {
            
$contents=array(); // For reg expression below
            
preg_match('|<{'.$section.'}>(.*)<{/'.$section.'}>|iUs'$this->level_tracker[$i]['****code****'], $contents);
            if (!empty(
$contents[1])) { // If we found the section
                
$found=true;
                if (
$i == 0) {
                    
$this->current_item=&$this->level_tracker[$i][$section]; // set current item reference
                
} else {
                    
// If no current iteration for section we are taking this out of, make one
                    
if (empty($this->level_tracker[$i][0]['****code****'])) {
                        
$this->level_tracker[$i][0]['****code****']=$this->level_tracker[$i]['****code****'];
                    }
                    
$num=$this->level_tracker[$i]['****current_iteration****']; // for below
                    
$this->current_item=&$this->level_tracker[$i][$num][$section]; // set current item
                
}
                
$this->level_tracker[$i+1]=&$this->current_item// add this to level_tracker
                
$this->current_level=$i+1// update current level
                
if (empty($this->current_item['****code****'])) { // not exist yet, setup
                    
$this->current_item['****code****']=$contents[1];
                    
$this->current_item['****current_iteration****']=0;
                }
                break;
            }
        }
        if (!
$found) {
            
$this->error("set_section()""No section found for '$section'");
        }
    }
    
    
// Go to next section iteration
    
public function next_section_iteration() {
        
$num=$this->current_item['****current_iteration****']; // get current number
        
if (empty($this->current_item[$num]['****code****'])) { // fill up current iteration if empty
            
$this->current_item[$num]['****code****']=$this->current_item['****code****'];
        }
        
$this->current_item['****current_iteration****']++; // increase number
    
}
    
    
// Go through arrays and get them ready to print
    // $array is the current array, $key is the name of the section, and $prev_array is the previous array (for setting code)
    
private function set_array_for_print(array &$array$key, array &$prev_array) {
        
$final=''// final code for the array
        
for ($i=0;$i<=$array['****current_iteration****'];$i++) { // go through all iterations of the array
            
if (!empty($array[$i])) {
                if (
is_array($array[$i])) {
                    foreach (
$array[$i] as $key2=>&$value) { // inside 0-9 array keys
                        
if ($key2 != '****code****') { // don't want to mess up ****code****
                            
$this->set_array_for_print(&$value$key2, &$array[$i]); // setup lower sections
                        
}
                    }
                    
$final.=$array[$i]['****code****']; // setup from previous $this->set_array_for_print()
                
}
            }
        }
        
// Replace section code in $code array with the final values for the loop
        
$prev_array['****code****']=preg_replace("|<{".$key."}>(.*)<{/".$key."}>|iUs"$final$prev_array['****code****']);
    }
    
    
// Gets the template ready to be printed
    
public function output() {
        
// go through the bottom of the level_tracker and start the recursive set_array_for_print function
        
foreach ($this->level_tracker[0] as $key=>&$value) {
            if (
$key != '****code****') { // only do it if not ****code**** (all others are real sections)
                
$this->set_array_for_print(&$value$key, &$this->level_tracker[0]);
            }
        }
        
$this->printed=true// set printed variable to say that it was printed
        
return $this->level_tracker[0]['****code****']; // return compiled code
    
}
    
    
// Destructs and prints out item
    
public function __destruct() {
        if (!
$this->printed) { // if not printed
            
echo $this->output(); // echo output
        
}
    }
}
?>




<< Prev123456789Next >>